#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Default values
JOBS=16
DATA=""
SERIALIZER=""
DEBUG_BUILD=false

# Parse arguments
usage() {
    echo "Usage: $0 [OPTIONS]"
    echo ""
    echo "Build and run C++ benchmarks"
    echo ""
    echo "Options:"
    echo "  --data <struct|sample>       Filter benchmark by data type"
    echo "  --serializer <fory|protobuf> Filter benchmark by serializer"
    echo "  --debug                      Build with debug symbols and low optimization for profiling"
    echo "  --help                       Show this help message"
    echo ""
    echo "Examples:"
    echo "  $0                          # Run all benchmarks"
    echo "  $0 --data struct            # Run only Struct benchmarks"
    echo "  $0 --serializer fory        # Run only Fory benchmarks"
    echo "  $0 --data struct --serializer fory"
    echo "  $0 --debug                  # Build for profiling (visible function names in flamegraph)"
    echo ""
    echo "For profiling/flamegraph, use: ./profile.sh"
    exit 0
}

while [[ $# -gt 0 ]]; do
    case $1 in
        --data)
            DATA="$2"
            shift 2
            ;;
        --serializer)
            SERIALIZER="$2"
            shift 2
            ;;
        --debug)
            DEBUG_BUILD=true
            shift
            ;;
        --help|-h)
            usage
            ;;
        *)
            echo -e "${RED}Unknown option: $1${NC}"
            usage
            ;;
    esac
done

# Build benchmark filter
FILTER=""
if [[ -n "$DATA" ]]; then
    DATA_CAP="$(echo "${DATA:0:1}" | tr '[:lower:]' '[:upper:]')${DATA:1}"
    FILTER="${DATA_CAP}"
fi
if [[ -n "$SERIALIZER" ]]; then
    SER_CAP="$(echo "${SERIALIZER:0:1}" | tr '[:lower:]' '[:upper:]')${SERIALIZER:1}"
    if [[ -n "$FILTER" ]]; then
        FILTER="${SER_CAP}_${FILTER}"
    else
        FILTER="${SER_CAP}"
    fi
fi

echo -e "${GREEN}=== Fory C++ Benchmark ===${NC}"
echo ""

# Step 1: Build
echo -e "${YELLOW}[1/3] Building benchmark...${NC}"
mkdir -p build
cd build
if [[ "$DEBUG_BUILD" == true ]]; then
    echo -e "${YELLOW}Building with debug symbols for profiling...${NC}"
    # Detect OS for platform-specific flags
    OS_TYPE="$(uname -s)"
    if [[ "$OS_TYPE" == "Darwin" ]]; then
        # macOS: Use -gfull for complete debug info, -fno-omit-frame-pointer for stack traces
        cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
              -DCMAKE_CXX_FLAGS="-O1 -gfull -fno-inline -fno-omit-frame-pointer -fno-optimize-sibling-calls" ..
    else
        # Linux
        cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
              -DCMAKE_CXX_FLAGS="-O1 -g -fno-inline -fno-omit-frame-pointer" ..
    fi
else
    cmake -DCMAKE_BUILD_TYPE=Release ..
fi
cmake --build . -j"$JOBS"
echo -e "${GREEN}Build complete!${NC}"
echo ""

# Step 2: Run benchmark
echo -e "${YELLOW}[2/3] Running benchmark...${NC}"
BENCH_ARGS="--benchmark_format=json --benchmark_out=benchmark_results.json"
if [[ -n "$FILTER" ]]; then
    BENCH_ARGS="$BENCH_ARGS --benchmark_filter=$FILTER"
    echo -e "Filter: ${FILTER}"
fi
./fory_benchmark $BENCH_ARGS
echo -e "${GREEN}Benchmark complete!${NC}"
echo ""

# Step 3: Generate report
echo -e "${YELLOW}[3/3] Generating report...${NC}"
cd "$SCRIPT_DIR"

# Check for Python dependencies
if ! python3 -c "import matplotlib" 2>/dev/null; then
    echo -e "${YELLOW}Installing required Python packages...${NC}"
    pip3 install matplotlib numpy psutil
fi

python3 benchmark_report.py --json-file build/benchmark_results.json --output-dir report
echo ""

echo -e "${GREEN}=== All done! ===${NC}"
echo -e "Report generated at: ${SCRIPT_DIR}/report/REPORT.md"
echo -e "Plots saved in: ${SCRIPT_DIR}/report/"
echo ""
echo -e "For profiling/flamegraph, run: ${YELLOW}./profile.sh --help${NC}"
